package com.cloopen.rest.sdk;

import cn.demoncat.util.exception.IoRuntimeException;
import cn.demoncat.util.lang.JsonUtil;
import cn.demoncat.util.lang.constant.CharsetConstant;
import cn.demoncat.util.lang.entity.MapSo;
import cn.demoncat.util.lang.entity.MapSs;
import com.alibaba.fastjson.JSONObject;
import com.cloopen.rest.sdk.utils.CcopHttpClient;
import com.cloopen.rest.sdk.utils.DateUtil;
import com.cloopen.rest.sdk.utils.EncryptUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@SuppressWarnings("deprecation")
public class CCPRestSmsSDK {

	private static final int GET = 0;
	private static final String SMS_TEMP = "SMS/TemplateSMS";
	private String serverIp;
	private String serverPort;
	private String accountSid;
	private String accountToken;
	private String appId;



	/**
	 * 初始化服务地址和端口
	 * 
	 * @param serverIP
	 *            必选参数 服务器地址
	 * @param serverPort
	 *            必选参数 服务器端口
	 */
	public void init(String serverIP, String serverPort) {
		if (isEmpty(serverIP) || isEmpty(serverPort)) {
			throw new IllegalArgumentException("必选参数:" + (isEmpty(serverIP) ? " 服务器地址 " : "") + (isEmpty(serverPort) ? " 服务器端口 " : "") + "为空");
		}
		this.serverIp = serverIP;
		this.serverPort = serverPort;
	}

	/**
	 * 初始化主帐号信息
	 * 
	 * @param accountSid
	 *            必选参数 主帐号名称
	 * @param accountToken
	 *            必选参数 主帐号令牌
	 */
	public void setAccount(String accountSid, String accountToken) {
		if (isEmpty(accountSid) || isEmpty(accountToken)) {
			throw new IllegalArgumentException("必选参数:" + (isEmpty(accountSid) ? " 主帐号名称" : "") + (isEmpty(accountToken) ? " 主帐号令牌 " : "") + "为空");
		}
		this.accountSid = accountSid;
		this.accountToken = accountToken;
	}


	/**
	 * 初始化应用Id
	 * 
	 * @param appId
	 *            必选参数 应用Id
	 */
	public void setAppId(String appId) {
		if (isEmpty(appId)) {
			throw new IllegalArgumentException("必选参数: 应用Id 为空");
		}
		this.appId = appId;
	}

	/**
	 * 发送短信模板请求
	 * 
	 * @param to
	 *            必选参数 短信接收端手机号码集合，用英文逗号分开，每批发送的手机号数量不得超过100个
	 * @param templateId
	 *            必选参数 模板Id
	 * @param datas
	 *            可选参数 内容数据，用于替换模板中{序号}
	 * @return
	 */
	public Map<String, String> sendTemplateSMS(String to, String templateId, String[] datas) {
		HashMap<String, String> validate = accountValidate();
		if(validate!=null) 
			return validate;
		if ((isEmpty(to)) || (isEmpty(appId)) || (isEmpty(templateId)))
			throw new IllegalArgumentException("必选参数:" + (isEmpty(to) ? " 手机号码 " : "") + (isEmpty(templateId) ? " 模板Id " : "") + "为空");
		DefaultHttpClient httpclient = null;
		String result = null;
		try {
			httpclient = CcopHttpClient.registerSSL(serverIp, "TLS", Integer.parseInt(serverPort), "https");
			HttpPost httppost = (HttpPost) getHttpRequestBase(1, SMS_TEMP);
			// 改GSON为FastJSON
			MapSo instance = MapSo.getInstance();
			instance.put("appId", appId);
			instance.put("to", to);
			instance.put("templateId", templateId);
			if (datas != null && datas.length > 0) {
				instance.put("datas", datas);
			}
			String requsetbody = JsonUtil.toString(instance);

			BasicHttpEntity requestBody = new BasicHttpEntity();
			requestBody.setContent(new ByteArrayInputStream(requsetbody.getBytes(StandardCharsets.UTF_8)));
			requestBody.setContentLength(requsetbody.getBytes(StandardCharsets.UTF_8).length);
			httppost.setEntity(requestBody);
			HttpResponse response = httpclient.execute(httppost);

			HttpEntity entity = response.getEntity();
			if (entity != null) {
				result = EntityUtils.toString(entity, CharsetConstant.UTF8);
			}
			EntityUtils.consume(entity);
		} catch (IOException e) {
			throw new IoRuntimeException("网络错误", e);
		} catch (Exception e) {
			throw new IoRuntimeException("网络无返回", e);
		}  finally {
			if (httpclient != null) {
				httpclient.getConnectionManager().shutdown();
				httpclient.close();
			}
		}
		
		try {
			return jsonToMap(result);
		} catch (Exception e) {
			throw new IoRuntimeException("网络响应错误", e);
		}
	}

	/**
	 * 解析响应体
	 * 
	 * @param result
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年1月9日
	 */
	private HashMap<String, String> jsonToMap(String result) {
		// 成功：{"statusCode":"000000","templateSMS":{"smsMessageSid":"5da5365aa6b7431ea796cc89201f5788","dateCreated":"20190109134133"}}
		// 失败：{"statusCode":"160038","statusMsg":"短信验证码发送过频繁"}
		// 改GSON为FastJSON
		JSONObject json = JsonUtil.parseObject(result);
		MapSs map = MapSs.getInstance("code", json.getString("statusCode"), "msg", json.getString("statusMsg"));
		if ("000000".equals(map.get("code"))) {
			map.put("sid", json.getJSONObject("templateSMS").getString("smsMessageSid"));
		}
		return map;
	}


	private HttpRequestBase getHttpRequestBase(int get, String action) throws NoSuchAlgorithmException, UnsupportedEncodingException {
		String timestamp = DateUtil.dateToStr(new Date(), DateUtil.DATE_TIME_NO_SLASH);
		EncryptUtil eu = new EncryptUtil();
		String sig;
		String acountName;
		String acountType = "Accounts";
		
		acountName = accountSid;
		sig = accountSid + accountToken + timestamp;
		String signature = eu.md5Digest(sig);

		String url = getBaseUrl().append("/").append(acountType).append("/").append(acountName).append("/").append(action).append("?sig=").append(signature).toString();
		HttpRequestBase mHttpRequestBase;
		if (get == GET){
			mHttpRequestBase = new HttpGet(url);
		}else {
			mHttpRequestBase = new HttpPost(url);
		}
		mHttpRequestBase.setHeader("Accept", "application/json");
		mHttpRequestBase.setHeader("Content-Type", "application/json;charset=utf-8");
		mHttpRequestBase.setHeader("Authorization", eu.base64Encoder(acountName + ":" + timestamp));
		return mHttpRequestBase;
	}

	private StringBuilder getBaseUrl() {
		StringBuilder sb = new StringBuilder();
		sb.append("https://");
		sb.append(serverIp).append(":").append(serverPort);
		sb.append("/2013-12-26");
		return sb;
	}

	private boolean isEmpty(String str) {
		return StringUtils.isBlank(str);
	}

	private HashMap<String, String> getMyError(String code, String msg) {
		HashMap<String, String> hashMap = new HashMap<>();
		hashMap.put("statusCode", code);
		hashMap.put("statusMsg", msg);
		return hashMap;
	}

	private HashMap<String,String> accountValidate() {
		if ((isEmpty(serverIp))) {
			return getMyError("172004", "IP为空");
		}
		if ((isEmpty(serverPort))) {
			return getMyError("172005", "端口错误");
		}
		if ((isEmpty(accountSid))) {
			return getMyError("172006", "主帐号为空");
		}
		if ((isEmpty(accountToken))) {
			return getMyError("172007", "主帐号令牌为空");
		}
		if ((isEmpty(appId))) {
			return getMyError("172012", "应用ID为空");
		}
		return null;
	}
}